﻿using System;
using System.Collections.Generic;
using System.Web.Security;
using System.Globalization;
using System.Net.Mail;
using System.Web;
using Medianamik.Core.Configuration;
using System.Configuration;
using System.Xml.Linq;
using Medianamik.Core.Logging;

namespace Medianamik.Core.Mail
{
    public class MailManager
    {
        private static readonly MedianamikConfigSection _config = (MedianamikConfigSection)ConfigurationManager.GetSection(ConfigurationSectionName.MEDIANAMIK);
        private const string RESOURCE_CLASS_KEY = "Medianamik_Emails";
        private const string SUPPORT_URL = "/Medianamik/login.aspx";

        private static ILogger _logger;
        private static ILogger Logger
        {
            get
            {
                return _logger
                    ?? (_logger = new ObjectFactory<ILogger>().Get("MailLogger"));
            }
        }

        public void SendNewUserConfirmationMessage(MembershipUser pUser, CultureInfo pCulture, string pPassword, HttpContext pContext)
        {
            var filename = "new-user-" + GetLoweredCultureName(pCulture) + ".htm";

            var mailDefinition = GetMailDefinition(filename, "NewUserConfirmationMessageSubject", pContext);

            string pathMedianamik = new Uri(pContext.Request.Url, "/Medianamik").ToString().TrimEnd('/');
            string urlSite = pContext.Request.Url.GetLeftPart(UriPartial.Authority);

            var replacements = new Dictionary<string, string>{
                {"#USERNAME#", pUser.UserName },
                { "#PASSWORD#", pPassword},
                { "#PATHMEDIANAMIK#", pathMedianamik},
                { "#URLSITE#", urlSite},
                { "#SUPPORTLINK#", BuildSupportUrl(pUser.UserName, pUser.Email, pContext).ToString()},
            };

            var message = mailDefinition.CreateMailMessage(new[] { pUser.Email }, replacements);

            try
            {
                new SmtpClient().Send(message);
            }
            catch
            {
                Logger.Error("Unable to send message via local smtp server");
            }
        }

        public void SendMessage(string emailSubject, string emailMessage, string emailSentTo)
        {
            var message = new MailMessage(_config.WebsiteFromMailAddress, emailSentTo);

            message.Subject = emailSubject;
            message.IsBodyHtml = false;
            message.Body = emailMessage;

            try
            {
                new SmtpClient().Send(message);
            }
            catch
            {
                Logger.Error("Unable to send message via local smtp server");
            }
        }

        public void SendPasswordChangedConfirmationMessage(MembershipUser pUser, CultureInfo pCulture, string pPassword, HttpContext pContext)
        {
            var filename = "password-changed-" + GetLoweredCultureName(pCulture) + ".htm";

            var mailDefinition = GetMailDefinition(filename, "PasswordChangedConfirmationMessageSubject", pContext);

            string pathMedianamik = new Uri(pContext.Request.Url, "/Medianamik").ToString().TrimEnd('/');
            string urlSite = pContext.Request.Url.GetLeftPart(UriPartial.Authority);
            var replacements = new Dictionary<string, string>{   
                {"#USERNAME#", pUser.UserName},
                {"#PASSWORD#", pPassword},
                {"#PATHMEDIANAMIK#", pathMedianamik},
                {"#URLSITE#", urlSite},
                {"#SUPPORTLINK#", BuildSupportUrl(pUser.UserName , pUser.Email, pContext).ToString()}
            };

            var message = mailDefinition.CreateMailMessage(new[] { pUser.Email }, replacements);

            try
            {
                new SmtpClient().Send(message);
            }
            catch
            {
                Logger.Error("Unable to send message via local smtp server");
            }
        }

        public void SendTechSupportRequestEmail(string pUsername, string pEmail, string pMessage,
            HttpContext pContext)
        {
            var filename = "support-request-" +
                GetLoweredCultureName(CultureInfo.CurrentUICulture) + ".htm";

            var mailDefinition = GetMailDefinition(filename, "SupportRequestMessageSubject", pContext);

            string pathMedianamik = new Uri(pContext.Request.Url, "/Medianamik").ToString().TrimEnd('/');
            string urlSite = pContext.Request.Url.GetLeftPart(UriPartial.Authority);

            var info = new XElement("p");
            info.Add(new HttpCookieCollectionTableBuilder(pContext.Request.Cookies,
                "Cookies").Build());
            info.Add(new NameValueCollectionTableBuilder(pContext.Request.QueryString,
                "Query String").Build());
            info.Add(new NameValueCollectionTableBuilder(pContext.Request.ServerVariables,
                "Server Variables").Build());

            var replacements = new Dictionary<string, string>
            {
                {"#USERNAME#", pUsername},
                {"#EMAIL#", pEmail},
                {"#USERAGENT", pContext.Request.UserAgent },
                {"#TEXTMAIL#", pMessage},
                {"#PATHMEDIANAMIK#", pathMedianamik},
                {"#URLSITE#", urlSite},
                {"#INFO#", info.ToString()}

            };

            var message = mailDefinition.CreateMailMessage(new[]
               {
                   _config.SupportMailAddress
               }, replacements);

            try
            {
                new SmtpClient().Send(message);
            }
            catch
            {
                Logger.Error("Unable to send message via local smtp server");
            }
        }

        public void SendTechSupportConfirmationEmail(string pUsername, string pEmail, string pMessage, HttpContext pContext)
        {
            var filename = "support-confirmation-" + GetLoweredCultureName(CultureInfo.CurrentUICulture) + ".htm";

            var mailDefinition = GetMailDefinition(filename, "SupportConfirmationMessageSubject", pContext);

            string pathMedianamik = new Uri(pContext.Request.Url, "/Medianamik").ToString().TrimEnd('/');
            string urlSite = pContext.Request.Url.GetLeftPart(UriPartial.Authority);

            var replacements = new Dictionary<string, string>
            {
                {"#USERNAME#", pUsername},
                {"#EMAIL#", pEmail},
                {"#TEXTMAIL#", pMessage},
                {"#PATHMEDIANAMIK#", pathMedianamik},
                {"#URLSITE#", urlSite},
            };

            var message = mailDefinition.CreateMailMessage(new[] { pEmail }, replacements);

            try
            {
                new SmtpClient().Send(message);
            }
            catch
            {
                Logger.Error("Unable to send message via local smtp server");
            }
        }

        public void SendPasswordRecoveryMessage(MembershipUser user, HttpContext context)
        {
            var filename = "password-recovery-" + GetLoweredCultureName(CultureInfo.CurrentUICulture) + ".htm";

            var mailDefinition = GetMailDefinition(filename, "PasswordRecoveryMessageSubject", context);

            var pathMedianamik = new Uri(context.Request.Url, "/Medianamik").ToString().TrimEnd('/');
            var urlSite = context.Request.Url.GetLeftPart(UriPartial.Authority);

            var replacements = new Dictionary<string, string>
            {
                {"#USERNAME#", user.UserName },
                {"#PASSWORD#", user.GetPassword() },
                {"#PATHMEDIANAMIK#", pathMedianamik},
                {"#URLSITE#", urlSite},
                {"#SUPPORTLINK#", BuildSupportUrl(user.UserName , user.Email, context).ToString()}
            };

            var message = mailDefinition.CreateMailMessage(new [] { user.Email }, replacements);

            try
            {
                new SmtpClient().Send(message);
            }
            catch
            {
                Logger.Error("Unable to send message via local smtp server");
            }
        }

        public void SendAccountLockedEmail(string pUsername, HttpContext pContext)
        {
            var filename = "account-locked-" + GetLoweredCultureName(CultureInfo.CurrentUICulture) + ".htm";

            var mailDefinition = GetMailDefinition(filename, "AccountLockedMessageSubject", pContext);

            var pathMedianamik = new Uri(pContext.Request.Url, "/Medianamik").ToString().TrimEnd('/');
            var urlSite = pContext.Request.Url.GetLeftPart(UriPartial.Authority);

            var replacements = new Dictionary<string, string>
            {
                {"#USERNAME#", pUsername},
                {"#USERAGENT", pContext.Request.UserAgent },
                {"#PATHMEDIANAMIK#", pathMedianamik},
                {"#URLSITE#", urlSite},

            };

            var message = mailDefinition.CreateMailMessage(new[] { _config.SupportMailAddress }, replacements);
            try
            {
                new SmtpClient().Send(message);
            }
            catch
            {
                Logger.Error("Unable to send message via local smtp server");
            }
        }

        private Uri BuildSupportUrl(string username, string email, HttpContext pContext)
        {
            string qs = "showsupportwindow=" + bool.TrueString
                + "&username=" + username
                + "&email=" + email;

            var url = new Uri(pContext.Request.Url, SUPPORT_URL + "?" + qs);

            return url;

        }

        private MailDefinition GetMailDefinition(string filename, string ResourceClassKey, HttpContext context)
        {
            var mailDefinition = new MailDefinition
                                 {
                                     From = _config.WebsiteFromMailAddress,
                                     IsBodyHtml = true,
                                     Subject = (string)HttpContext.GetGlobalResourceObject(RESOURCE_CLASS_KEY, ResourceClassKey)
                                 };

            if (string.IsNullOrEmpty(_config.EmailTemplateFolderPath))
                mailDefinition.BodyResourceName = "Mail." + filename;
            else
                mailDefinition.BodyFilePath = context.Server.MapPath(_config.EmailTemplateFolderPath) + filename;

            return mailDefinition;
        }

        /// <summary>
        /// Retourne fr-ca ou en-ca selon la culture passée.
        /// La culture par défaut est une configuration du web.Config
        /// </summary>
        /// <param name="pCulture"></param>
        /// <returns></returns>
        private string GetLoweredCultureName(CultureInfo pCulture)
        {
            var loweredCultureName = pCulture.Name.ToLower();
            switch (loweredCultureName)
            {
                case "fr-ca":
                case "en-ca":
                    return loweredCultureName;
                default:
                    return _config.DefaultUICultureName.ToLower();

            }
        }
    }
}